﻿using System.Collections;
using System.Collections.Generic;

namespace NRank.Common
{
	public interface IDepthAwareContainer
	{
		//DepthAware<IRanked<T1>> LeftSource { get; }
		//DepthAware<IRanked<T1>> RightSource { get; }
		int LeftDepth { get; }
		int RightDepth { get; }
	}

	/// <summary>
	/// Collection wrapper extended by current depth counter. When enumerated, items from inner
	/// collection are obtained, but this class counts how many items has been seen, thus user
	/// knows the current 'depth' of the input.
	/// </summary>
	/// <typeparam name="T">Type of item</typeparam>
	public class DepthAware<T> : IEnumerable<T>
	{
		/// <summary>
		/// Original items
		/// </summary>
		private readonly IEnumerable<T> source;

		/// <summary>
		/// Creates instance of DepthAware
		/// </summary>
		/// <param name="source">Original items</param>
		public DepthAware(IEnumerable<T> source)
		{
			this.source = source;
			this.Depth = 0;
		}

		/// <summary>
		/// Current depth
		/// </summary>
		public int Depth { get; private set; }

		/// <summary>
		/// Enumerates through items and counts current depth
		/// </summary>
		/// <returns></returns>
		private IEnumerable<T> GetItems()
		{
			foreach (var item in source)
			{
				++this.Depth;
				yield return item;
			}
		}

		/// <summary>
		/// Items' enumerator
		/// </summary>
		/// <returns>Items' enumerator</returns>
		public IEnumerator<T> GetEnumerator()
		{
			return GetItems().GetEnumerator();
		}

		/// <summary>
		/// Nongeneric items' enumerator
		/// </summary>
		/// <returns>Nongeneric items' enumerator</returns>
		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}
	}

	/// <summary>
	/// Helper class for type inference
	/// </summary>
	public static class DepthAware
	{
		/// <summary>
		/// Creates collection wrapper with depth counter
		/// </summary>
		/// <typeparam name="T">Type of collection</typeparam>
		/// <param name="source">Original collection</param>
		/// <returns>Collection wrapper with depth counter</returns>
		public static DepthAware<T> AsDepthAware<T>(this IEnumerable<T> source)
		{
			return new DepthAware<T>(source);
		}
	}
}